home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / Apple Game Sprockets / InputSprocket / Sample Drivers / ISp Sample ADB Sources / ADBUtils.cp next >
Encoding:
Text File  |  1998-07-14  |  6.2 KB  |  250 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************
  2.  
  3. File:      ADBUtils.cp
  4.  
  5. Copyright © 1996, 1997, 1998 Apple Computer, Inc., All Rights Reserved
  6.  
  7.  
  8. You may incorporate this sample code into your applications without
  9. restriction, though the sample code has been provided "AS IS" and the
  10. responsibility for its operation is 100% yours.  However, what you are
  11. not permitted to do is to redistribute the source as "DSC Sample Code"
  12. after having made changes. If you're going to re-distribute the source,
  13. we require that you make it clear in the source that the code was
  14. descended from Apple Sample Code, but that you've made changes.
  15.  
  16. *************************************************************************************/
  17.  
  18.  
  19. #include "ADBUtils.h"
  20. #include "Common.h"
  21.  
  22. #ifndef __DESKBUS__
  23. #include <DeskBus.h>
  24. #endif
  25.  
  26. #if !TARGET_CPU_PPC
  27. #ifndef __TRAPS__
  28. #include <Traps.h>
  29. #endif
  30. #endif
  31.  
  32. enum
  33. {
  34.     kADBCommand_SendReset    = 0x00,
  35.     kADBCommand_Flush        = 0x01,
  36.     kADBCommand_Listen        = 0x08,
  37.     kADBCommand_Talk        = 0x0c
  38. };
  39.  
  40.  
  41. // globals
  42. volatile UInt32 gComplete;
  43.  
  44. #if TARGET_CPU_PPC
  45. pascal void MyADBOpCompletionRoutine(Ptr dataBuffPtr, Ptr opDataAreaPtr, long command);
  46.  
  47. static RoutineDescriptor gRDMyADBOpCompletionRoutine    = BUILD_ROUTINE_DESCRIPTOR(uppADBCompletionProcInfo, MyADBOpCompletionRoutine);
  48. static UniversalProcPtr gUPPMyADBOpCompletionRoutine = &gRDMyADBOpCompletionRoutine;
  49.  
  50. pascal void MyADBOpCompletionRoutine(Ptr dataBuffPtr, Ptr opDataAreaPtr, long command)
  51. {
  52.     dataBuffPtr;
  53.     opDataAreaPtr;
  54.     command;
  55.     
  56.     gComplete = true;
  57. }
  58.  
  59. #define ADBOp_Glue     ADBOp
  60.  
  61. #else    // !TARGET_CPU_PPC
  62.  
  63. /*    Because on some OSs, CFM for 68k is very sensitive to interrupts, especially
  64.     a CFM switch called FROM and interrput, the ADB callback is in straight 68k runtime
  65.     this involves some tweaks to bypass the CFM glue for ADBOp and callback
  66. */
  67.  
  68. //#pragma parameter __D0 ADBOp_asm(__A0,__D0)
  69. asm OSErr ADBOp_asm(ADBOpBlock * pb, short commandNum);
  70.  
  71. OSErr ADBOp_Glue (Ptr refCon, ADBCompletionUPP compRout, Ptr buffer, short commandNum);
  72. asm void MyADBOpCompletionRoutine(void);
  73.  
  74. #define    gUPPMyADBOpCompletionRoutine    (* (UniversalProcPtr *) MyADBOpCompletionRoutine)
  75.  
  76. /*
  77.     ADBOp has a different interface for 68k assembly than for everything else
  78.     for 68k assembly the interface is 
  79.     #pragma parameter __D0 ADBOp(__A0,__D0)
  80.     OSErr ADBOp( ADBOpBlock * pb, short commandNum );
  81.  
  82.     struct ADBOpBlock {
  83.         Ptr                     dataBuffPtr;    // buffer: pointer to variable length data buffer
  84.         ADBServiceRoutineUPP     opServiceRtPtr;    // completionProc: completion routine pointer
  85.         Ptr                     opDataAreaPtr;    // refCon: this field is passed as the refCon parameter to the completion routine
  86.     };
  87. */
  88. #pragma parameter __D0 ADBOp_asm(__A0,__D0)
  89. asm OSErr ADBOp_asm(ADBOpBlock * pb, short commandNum)
  90. {
  91.     _ADBOp
  92.     rts
  93. }
  94.  
  95. OSErr ADBOp_Glue (Ptr refCon, ADBCompletionUPP compRout, Ptr buffer, short commandNum)
  96. {
  97.     ADBOpBlock    pb;
  98.     
  99.     pb.dataBuffPtr = buffer;
  100.     pb.opServiceRtPtr = compRout;
  101.     pb.opDataAreaPtr = refCon;
  102.     
  103.     return ADBOp_asm(&pb, commandNum);
  104. }
  105.  
  106. asm void MyADBOpCompletionRoutine(void)
  107. {
  108.     move.l    #1, (A2)        // set *opDataAreaPtr
  109.     rts
  110. }
  111.  
  112. #endif    //!TARGET_CPU_PPC
  113.  
  114.  
  115. #if TARGET_CPU_PPC
  116. #define Debugger_Inline()     Debugger()
  117. #else
  118. void Debugger_Inline(void) = { 0xa9ff };
  119. #endif
  120.  
  121. //
  122. // synchronus version of ADBOp
  123. //
  124.  
  125. static OSErr ADBOpSync(UInt8 *buffer, short commandNum)
  126. {
  127.     OSErr err;
  128.  
  129.     // we haven't finished the command yet
  130.     gComplete = false;
  131.     
  132.     err = ADBOp_Glue((Ptr) &gComplete, gUPPMyADBOpCompletionRoutine, (Ptr) buffer, commandNum);
  133.  
  134.     // if there was no error wait sync for it to complete
  135.     if (err == noErr)
  136.     {
  137.         while(!gComplete) { } 
  138.     }
  139.  
  140.     return err;
  141. }
  142.  
  143. void ADBOp_SendResetSync(void)
  144. {
  145.     OSErr err;
  146.     short commandNum = kADBCommand_SendReset;
  147.  
  148.     // loop until we can send the command
  149.     do
  150.     {
  151.         err = ADBOpSync(nil, commandNum);
  152.     } while (err != noErr);
  153. }
  154.  
  155. void ADBOp_FlushSync(ADBAddress address)
  156. {
  157.     WARNING(address <= 15,    "bad address passed to ADBFlush");
  158.  
  159.     OSErr err;
  160.     short commandNum = address << 4 | kADBCommand_Flush;
  161.  
  162.     // loop until we can send the command
  163.     do
  164.     {
  165.         err = ADBOpSync(nil, commandNum);
  166.     } while (err != noErr);
  167. }
  168.  
  169. void ADBOp_ListenSync(ADBAddress address, UInt8 reg, const ADBRegister data)
  170. {
  171.     WARNING(reg <= 4,         "bad register passed to ADBListenSync");
  172.     WARNING(address <= 15,    "bad address passed to ADBListenSync");
  173.     WARNING(data[0] <= 8,    "data to long passed to ADBListenSync");
  174.     WARNING(data != nil,    "nil data passed to ADBListenSync");
  175.         
  176.     OSErr err;
  177.     short commandNum = address << 4 | kADBCommand_Listen | reg;
  178.     
  179.     // loop until we can send the command
  180.     do
  181.     {
  182.         // we are converting a const UInt8 * to a UInt8 *
  183.         // this is to the interface to ADBOpSync
  184.         err = ADBOpSync((UInt8 *) data, commandNum);
  185.     } while (err != noErr);
  186. }
  187.  
  188. void ADBOp_TalkSync(ADBAddress address, UInt8 reg, ADBRegister data)
  189. {
  190.     WARNING(reg <= 4,         "bad register passed to ADBTalkSync");
  191.     WARNING(address <= 15,    "bad address passed to ADBTalkSync");
  192.     WARNING(data != nil,    "nil data passed to ADBTalkSync");
  193.  
  194.     OSErr err;
  195.     short commandNum = address << 4 | kADBCommand_Talk | reg;
  196.  
  197.     // loop until we can send the command
  198.     do
  199.     {
  200.         err = ADBOpSync(data, commandNum);
  201.     } while(err != noErr);
  202. }
  203.  
  204. void ADBOp_TalkReliableSync(ADBAddress address, UInt8 reg, ADBRegister data)
  205. {
  206.     WARNING(reg <= 4,         "bad register passed to ADBTalkSyncReliable");
  207.     WARNING(address <= 15,    "bad address passed to ADBTalkSyncReliable");
  208.  
  209.     const UInt32 numRetries = 5;    // number of times we will retry on a zero length
  210.     UInt32 emptyItr;                // count of our retries
  211.     
  212.     for(emptyItr = 0; emptyItr < numRetries; emptyItr++)
  213.     {
  214.         ADBOp_TalkSync(address, reg, data);
  215.         
  216.         if (data[0] != 0) { break; }    // read something break return
  217.     }
  218. }
  219.  
  220. Boolean ADBOp_ChangeHandlerIDSync(ADBAddress inAddress, UInt8 inNewHandlerID)
  221. {
  222.     Boolean success;
  223.     UInt8 data[9];
  224.  
  225.     // == read our register 3  == 
  226.     ADBOp_TalkReliableSync(inAddress, 3, data);
  227.     
  228.     // correct length ?
  229.     if (data[0] != 2) { return false; }
  230.  
  231.     // set the new handler id
  232.     data[2] = inNewHandlerID;
  233.  
  234.     // == write our register 3 ==
  235.     ADBOp_ListenSync(inAddress, 3, data);
  236.     
  237.     // == read our register 3  == 
  238.     ADBOp_TalkReliableSync(inAddress, 3, data);
  239.     
  240.     // correct length ?
  241.     if (data[0] != 2) { return false; }    
  242.     
  243.     // did it change to the correct value ?
  244.     if (data[2] == inNewHandlerID) { success = true; }
  245.     else { success = false; }
  246.  
  247.     return success;
  248. }
  249.  
  250.